package com.tianchi.lexiang.socketclient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import com.tianchi.lexiang.constant.Commands;
import com.tianchi.lexiang.util.SyncDBUtil;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * Quick Server Client
 * 
 */
public class SocketConnectUtil {

	private static final String TAG = "SocketConnectUtil";
	private static Socket socket;

	private BufferedReader in;
	private PrintWriter streamWriter;
	private static int threadNum;
	
	private boolean dead = false;
	
	private static SocketConnectUtil connect;
	
	public static final String SERVER_IP = "192.168.43.1";
	public static final int SERVER_PORT = 9596;
	
	private List<Handler> handlerList = new ArrayList<Handler>(1);
	
	public void register(Handler mHander){
		handlerList.add(mHander);
	}
	
	public synchronized static SocketConnectUtil getSocketConnectUtil() throws UnknownHostException, IOException{
		if(connect == null || socket == null){
			connect = new SocketConnectUtil(++threadNum,SERVER_IP,SERVER_PORT);
		}
		return connect;
	}
	
	
	public BufferedReader getBufferedReader() throws IOException {
		return new BufferedReader(new InputStreamReader(socket.getInputStream()));
	}

	public PrintWriter getPrintWriter() throws IOException {
		return new PrintWriter(socket.getOutputStream(),true);
	}

	public boolean isClosed(){
		return socket == null || socket.isClosed();
	}
	
	private SocketConnectUtil(int threadMnum, int port) throws UnknownHostException, IOException {
		this(threadMnum, "localhost", port);
	}
	
	private SocketConnectUtil(int threadMnum, String serverIP, int port) throws UnknownHostException, IOException {
			socket = new Socket(serverIP, port);
			dead = false;
			Log.d(TAG, "create a new socket=>"+socket);
			in = getBufferedReader();
			streamWriter = getPrintWriter();
			
			new Thread() {
				public void run() {
					receiveSocket();
				}
			}.start();
	}
	
	public void disconnect(){
		try {
			dead = true;
			if (in != null) {
				Log.d(TAG, "[disconnect] close in");
				in = null;
			}
			if (streamWriter != null) {
				streamWriter.close();
				streamWriter = null;
			}
			handlerList.clear();
			if (socket != null ) {
				socket.close();
			}
			threadNum = 0;
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public int getThreadNum() {
		return threadNum;
	}

	public synchronized boolean sendSocket(String cmd){
		if(socket!=null&&!socket.isClosed()){
			try{
				Log.d(TAG, "[sendSocket] cmd==>" + cmd);
				streamWriter.println(cmd);
				checkSocket();
			}catch (Exception e) {
				try {
					socket.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				Log.e(TAG, "send socket accur error,e="+e.getMessage());
				return false;
			}
		}
		return true;
	}
	
	private void checkSocket() throws UnknownHostException, IOException{
		getSocketConnectUtil();	
	}
	
	
	private void receiveSocket(){
		try {
			in = getBufferedReader();
			Log.d(TAG, "[receiveSocket]  inputstream is null ,retrieve in=>" + in);
		} catch (IOException e) {
			e.printStackTrace();
		}
		String line ;
		try {
			Commands cmdObj = null;
			while ( !dead && (line = in.readLine()) != null) {
				Log.d(TAG, "[receiveSocket] line==>" + line);
				if (line.length() != 0) {
					if (line.contains(Commands.CMD_TYPE)) {
						cmdObj = new Commands("", "");
						cmdObj.setCmdType(line.split("=")[1]);
					}else if(line.contains(Commands.CMD_COTENT)){
						final String[] arr = line.split("=");
						if (arr.length == 2) {
							cmdObj.setCmdContent(line.split("=")[1]);
						}else {
							Log.d(TAG, "cmd content is null");
							cmdObj.setCmdContent("");
						}
					}else {
						Log.d(TAG, "[else] " + line);
//						if (SyncDBUtil.getInstance().isPrepare()) {
//							SyncDBUtil.getInstance().writeToFile(line.getBytes());
//						}
					}
				}else {
					if (SyncDBUtil.getInstance().isPrepare()) {
						Log.d(TAG, "sync db util will close");
						SyncDBUtil.getInstance().close();
					}else {
						Log.d(TAG, "will call dispatchCmds cmdObj=>"+cmdObj);
						dispatchCmds(cmdObj);
					}
				}
			}
		} catch (IOException e) {
			Log.d(TAG, "[receiveSocket]",e);
			e.printStackTrace();
		}finally{
			try{
				dead = true;
				if (in != null) {
					in.close();
					in = null;
				}
				if (socket != null) {
					socket.close();
					socket = null;
				}
			}catch(Exception e1){
				Log.e(TAG,e1.getMessage(),e1);
			}
		}
	}
	
	private void dispatchCmds(Commands cmd){
		Log.d(TAG, "[dispatchCmds] handlerList.size()==" + handlerList.size());
		for (Handler mHandler : handlerList) {
			Message msg = mHandler.obtainMessage();
			msg.obj = cmd;
			msg.sendToTarget();
		}
	}
	
	public interface OnNewConnection{
		public void onNewConnectionConnect();
	}
}
